package fons.model.ontology.calculation;

import java.util.List;
import java.util.Map;


import com.google.common.collect.Lists;

import fons.model.ontology.Context;
import fons.model.ontology.Dimension;
import fons.model.ontology.SimpleMeasurement;
import fons.model.ontology.Value;
import fons.model.ontology.calculation.expression.VariableMissingException;

public class ResultDefinition {

	private final Context context;
	private final List<VariableDefinition> variables = Lists.newArrayList();
	private final List<DynamicDimensionDefinition> ddds = Lists.newArrayList();
	private final Calculation calculation;
	
	private SimpleMeasurement measurement;
 	
	public ResultDefinition(Context context, Calculation calculation) {
		this.context = context;
		this.calculation = calculation;
	}

	public void use(VariableDefinition definition) {
		variables.add(definition);
	}

	public void addDimension(String definition) {
		ddds.add(new DynamicDimensionDefinition(definition));
	}

	public void addDimension(DynamicDimensionDefinition ddd) {
		ddds.add(ddd);
	}
	
	public void setMeasurement(SimpleMeasurement measurement) {
		this.measurement = measurement;
	}
	
	public void setMeasurement(String measurement) {
		this.measurement = context.getMeasurement(measurement);
	}
	
	public Value getResult(final Map<String, Variable> realVariables) {
		try {
			final Value result = calculation.calculate(context, realVariables);
			if (result == Context.missingValue) return result;
			
			for (DynamicDimensionDefinition ddd: ddds) {
				final Dimension dim = context.getDimension(ddd.use(realVariables));
				if (ddd.hasParent()) {
					dim.childOf(ddd.getParent());
				}
				result.as(dim);
			}
			
			result.in(measurement);
			
			return result;
			
		} catch (VariableMissingException ex) {
			return Context.missingValue;
		}		
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder("ResultDefinition [variables=\n");
		for (VariableDefinition v: variables) {
			builder.append("\t");
			builder.append(v);
			builder.append("\n");
		}
		builder.append("\nddds=\n");
		for (DynamicDimensionDefinition ddd: ddds) {
			builder.append("\t" + ddd +"\n");
		}
		builder.append("measurement=" + measurement + "]");
		
		return builder.toString();
	}

	public void use(List<VariableDefinition> variableDefinitions) {
		for (VariableDefinition def: variableDefinitions) {
			this.use(def);
		}
	}
	
	
}
